package advice;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * Author:shixiaojun@itany.com
 * Date:2022/3/9 9:36
 * Version:1.0-SNAPSHOT
 */
@Component
@Aspect
public class LogAdvice {

    // 定义一个切点表达式
    // 该切点表达式的id属性值即为当前的方法名,括号不能省略
    // 此处即为:pointcutName()
    @Pointcut("execution(* service.impl.*.*(..))")
    public void pointcutName(){}

    // value属性:指定当前通知所引用的切点表达式是谁
    // 当某个注解中有且仅有value属性时,可以将value省略,直接写值即可
//    @Before(value = "pointcutName()")
    @Before("pointcutName()")
    public void before(JoinPoint jp){
        System.out.println("前置通知:"+jp.getSignature().getName()+"方法即将执行,参数为:"+ Arrays.toString(jp.getArgs()));
    }

    @AfterReturning(value = "pointcutName()",returning = "returnValue")
    public void afterReturning(JoinPoint jp,Object returnValue){
        System.out.println("正常返回通知:"+jp.getSignature().getName()+"方法执行成功,返回值为:"+returnValue);
    }

    @AfterThrowing(value = "pointcutName()",throwing = "e")
    public void afterThrowing(JoinPoint jp,Exception e){
        System.out.println("异常通知:"+jp.getSignature().getName()+"方法执行遇到了异常,异常为:"+e.getMessage());
    }

    @After("pointcutName()")
    public void after(JoinPoint jp){
        System.out.println("后置通知:"+jp.getSignature().getName()+"方法执行结束");
    }

    @Around("pointcutName()")
    public Object around(ProceedingJoinPoint jp) throws Throwable{
        try {
            System.out.println("环绕通知之前置通知");
            Object result = jp.proceed();
            System.out.println("环绕通知之正常返回通知");
            return result;
        } catch (Throwable e) {
            System.out.println("环绕通知之异常通知");
            throw e;
        }finally {
            System.out.println("环绕通知之后置通知");
        }
    }
}
